#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Version: Python 2.6.6
# Author: Sergey K.
# Created: 2011-10-26


import unittest

import rs
import rs.cache
import rs.resource


@rs.get
@rs.path('/resource')
@rs.cache.tag()
@rs.cache.control(maxage='1000')
def get_resource(request=rs.context.request):
    entity = 'resource'
    #request.check_preconditions(entity) # raise 304 Not Modified
    return entity

@rs.put
@rs.path('/resource')
@rs.cache.tag(etag=id)
def put_resource(request=rs.context.request):
    entity = 'resource'
    #request.check_preconditions(entity) # raise 412 Precondition Failed
    return entity


class TagTest(unittest.TestCase):

    def test_init(self):
        true = self.assertTrue
        tag = rs.cache.Tag(id)
        true(tag.etag is id)
        true(tag.last_modified.im_func is rs.cache.Tag.last_modified.im_func)

    def test_set(self):
        eq = self.assertEquals
        e = {'id':0, 'name':'TestEntity', 'created':'2011-10-31 00:00'}
        h = {}
        tag = rs.cache.Tag()
        tag.set(h, e)
        eq(0, len(h))
        tag = rs.cache.Tag(lambda e: e['id'], lambda e: e['created'])
        h = {}
        tag.set(h, e)
        eq(2, len(h))
        eq('"0"', h['etag'])
        eq('2011-10-31 00:00', h['last-modified'])

    def test_get_etag(self):
        eq = self.assertEquals
        tag = rs.cache.Tag(etag=lambda e: e)
        eq(None, tag.get_etag(None))
        eq('"1"', tag.get_etag(1))
        eq('"1"', tag.get_etag('1'))
        eq('"1 "', tag.get_etag('1 '))
        eq('W/"1 "', tag.get_etag('W/"1 "'))
        try:
            tag.get_etag('"')
        except ValueError:
            pass
        else:
            self.fail('ValueError expected.')

    def test_get_last_modified(self):
        import datetime
        eq = self.assertEquals
        tag = rs.cache.Tag(last_modified=lambda e: e)
        eq(None, tag.get_last_modified(None))
        eq('Mon, 31 Oct 2011 21:17:45 GMT',
           tag.get_last_modified(datetime.datetime(2011, 10, 31, 21, 17, 45)))
        try:
            tag.get_last_modified(1)
        except ValueError:
            pass
        else:
            self.fail('ValueError expected.')

    def test_custom_tag(self):
        class TestTag(rs.cache.Tag):
            def etag(self, entity):
                return 'custom ETag'
            def last_modified(self, entity):
                return 'custom Last-Modified'
        tag = TestTag()
        eq = self.assertEquals
        h = {}
        tag.set(h, None)
        eq('"custom ETag"', h['etag'])
        eq('custom Last-Modified', h['last-modified'])


class CacheControlTest(unittest.TestCase):

    def test_get_values(self):
        eq = self.assertEquals
        true = self.assertTrue
        cc = rs.cache.CacheControl()
        v = cc.get_values(None)
        eq(0, len(v))
        v = cc.get_values('no-cache, s-maxage=600')
        eq(2, len(v))
        true('no-cache' in v)
        true('s-maxage' in v)
        eq('600', v['s-maxage'])
        cc = rs.cache.CacheControl(maxage='900', public=True)
        v = cc.get_values(None)
        eq(2, len(v))
        true('public' in v)
        true('max-age' in v)
        eq('900', v['max-age'])
        v = cc.get_values('max-age=500, must-revalidate')
        eq(3, len(v))
        true('public' in v)
        true('max-age' in v)
        true('must-revalidate' in v)
        eq('500', v['max-age'])
        cc = rs.cache.CacheControl(maxage=0, data='must-revalidate, public')
        v = cc.get_values(None)
        eq(3, len(v))
        true('public' in v)
        true('max-age' in v)
        true('must-revalidate' in v)
        eq('0', v['max-age'])

    def test_set(self):
        eq = self.assertEquals
        true = self.assertTrue
        cc = rs.cache.CacheControl()
        h = {}
        cc.set(h)
        true('cache-control' in h)
        eq('no-cache', h['cache-control'])
        h = {'etag':''}
        cc.set(h)
        true('cache-control' in h)
        eq('must-revalidate, private', h['cache-control'])
        h = {'last-modified':''}
        cc.set(h)
        true('cache-control' in h)
        eq('must-revalidate, private', h['cache-control'])
        h = {'expires':''}
        cc.set(h)
        true('cache-control' in h)
        eq('must-revalidate, private', h['cache-control'])
        cc = rs.cache.CacheControl(maxage=1000)
        h = {}
        cc.set(h)
        true('cache-control' in h)
        eq('private, max-age=1000', h['cache-control'])
        cc = rs.cache.CacheControl(maxage=1000, public=True)
        h = {}
        cc.set(h)
        true('cache-control' in h)
        eq('public, max-age=1000', h['cache-control'])
        cc = rs.cache.CacheControl(data='no-cache', smaxage=10000)
        h = {}
        cc.set(h)
        true('cache-control' in h)
        eq('no-cache, s-maxage=10000', h['cache-control'])
        h= {'cache-control' : 'private, max-age=700, s-maxage=600'}
        cc.set(h)
        true('cache-control' in h)
        eq('s-maxage=600, no-cache, private, max-age=700', h['cache-control'])
        


class CacheManagerTest(unittest.TestCase):
    
    def test_init(self):
        eq = self.assertEquals
        true = self.assertTrue
        cache = rs.cache.CacheManager(rs.resource.build_all([put_resource, get_resource]))
        true(hasattr(cache, 'cache'))
        eq(2, len(cache.cache))
        true(get_resource in cache.cache)
        true(put_resource in cache.cache)

    def test_get_cache(self):
        eq = self.assertEquals
        true = self.assertTrue
        res = rs.resource.build(get_resource)
        cache = rs.cache.CacheManager(res)
        entry = cache.get_cache(res[0])
        true(entry is not rs.cache.CacheManager.EmptyEntry)
        true(entry.cache_control is not None)
        true(entry.tag is not None)
        eq('1000', entry.cache_control.maxage)
        eq(rs.cache.Tag.etag.im_func, entry.tag.etag.im_func)
        eq(rs.cache.Tag.last_modified.im_func, entry.tag.last_modified.im_func)
        dummy = rs.resource.Resource()
        dummy.target = put_resource
        entry = cache.get_cache(dummy)
        true(entry is not None)
        true(entry is rs.cache.CacheManager.EmptyEntry)
        

if __name__ == '__main__':
    unittest.main()